﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Asol.Reporting.Editor.Editor;
using Asol.Reporting.Editor.Components;
using Asol.Reporting.Editor.Data;
using Asol.Reporting.Support;
using Asol.Reporting.Support.Components;

namespace Asol.Reporting.Editor.Forms
{
	/// <summary>
	/// Editor FRX sestavy, celé okno: dokument, toolbar, editor, property grid, status bar.
    /// Slouží jako adaptér na odpovídající metody / property svých jednotlivých prvků (UI, Editor, PropertyPanel).
    /// Tyto prvky nejsou public, musí na ně vést cesta přes EditorForm.
    /// Editor typicky nemá public eventy, které by mířily do Dokumentu: vnitřní eventy zpracovává sám a volá odpovídající metody dokumentu (nikoli eventhandlery).
	/// </summary>
	public partial class EditorForm : DForm
	{
		#region Konstrukce
		/// <summary>
		/// Konstruktor
		/// </summary>
		public EditorForm()
		{
			InitializeComponent();
            InitForm();
            InitUI();
            InitEditor();
			InitPropertyGrid();
			InitDocument();
		}
        /// <summary>
        /// Pokračování inicializace formu
        /// </summary>
        private void InitForm()
        {
            // Steward.Diagnostic.InfoClear(true);
            this.FormClosed += new FormClosedEventHandler(EditorForm_FormClosed);
        }
        private void EditorForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Steward.Diagnostic.Save();
            // Steward.Diagnostic.Open();
        }
		#endregion
		#region User Interface
        /// <summary>
        /// Inicializace UI
        /// </summary>
		private void InitUI()
        {
            this._EditorUI = new Editor.EditorUI();
            this._EditorUI.CommandExecute += new EditorCommandExecuteHandler(_EditorUI_CommandExecute);
            this._EditorUI.CreateUI(this._ToolStripTop, this._ToolStripLeft, this._ToolStripRight);
        }
        /// <summary>
        /// Objektu UI, který řeší celou logiku UI (tvorbu dle konfigurace, aktivitu, refreshe)
        /// </summary>
        private EditorUI _EditorUI;
        /// <summary>
        /// Privátní handler pro událost, kdy na UI došlo k požadavku na akci
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _EditorUI_CommandExecute(object sender, EditorCommandExecuteArgs args)
        {
            this.CallDocumentCommandExecute(args);
        }
        #endregion
        #region Editor
        /// <summary>
        /// Inicializace editoru
        /// </summary>
        protected void InitEditor()
        {
            this._ReportEditor.Initialize();
        }
        #endregion
		#region PropertyGrid
        /// <summary>
        /// Inicializace PropertyGridu
        /// </summary>
		protected void InitPropertyGrid()
		{
            this._PropertyPanel.CommandsVisibleIfAvailable = false;
            this._PropertyPanel.Enter += new EventHandler(this.PropertyPanel_Enter);
            this._PropertyPanel.ComboSelectedIndexChanged += new EventHandler(PropertyPanel_ComboSelectedIndexChanged);
            this._PropertyPanel.SelectedGridItemChanged += new SelectedGridItemChangedEventHandler(PropertyPanel_SelectedItemChanged);
			this._PropertyPanel.PropertyValueChanged += new PropertyValueChangedEventHandler(PropertyPanel_PropertyValueChanged);
		}
        /// <summary>
		/// Po změně aktivního řádku v property gridu
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
        void PropertyPanel_Enter(object sender, EventArgs e)
		{
            this.CallDocumentPropertyPanelEnter();
		}
		/// <summary>
		/// Po změně aktivního řádku v property gridu
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void PropertyPanel_SelectedItemChanged(object sender, SelectedGridItemChangedEventArgs e)
		{
		}
		/// <summary>
		/// Po změně hodnoty určité vlastnosti v property gridu
		/// </summary>
		/// <param name="s"></param>
		/// <param name="e"></param>
		void PropertyPanel_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
		{
            this.CallDocumentPropertyValueChanged(e);
            this._ReportEditor.ReDraw();
		}
        /// <summary>
        /// Po změně vybraného objektu v combo boxu nad PropertyGridem
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PropertyPanel_ComboSelectedIndexChanged(object sender, EventArgs e)
        {
            this.CallDocumentPropertyComboChanged();
        }
        
		#endregion
        #region PdfPreview

        public void ShowPdfContent(byte[] content)
        {
            this._PdfView.LoadContent(content, this.Document.DocumentFile);
            this.EditorContent = EditorContentType.PdfPreview;
            this.Document.UIRefresh();
        }
        public void ShowEditor()
        {
            this.EditorContent = EditorContentType.Editor;
            this.Document.UIRefresh();
        }
        #endregion
        #region Přepínání editoru a preview
        /// <summary>
        /// Aktuálně viditelný obsah: Editor / PdfView
        /// </summary>
        public EditorContentType EditorContent
        {
            get { return this._EditorContent; }
            set
            {
                this._EditorContent = value;
                this._MainSplit.Visible = (this._EditorContent == EditorContentType.Editor);
                this._PdfView.Visible = (this._EditorContent == EditorContentType.PdfPreview);
            }
        }
        private EditorContentType _EditorContent = EditorContentType.Editor;
        /// <summary>
        /// Zobrazovaný obsah okna editoru: editor / PDF preview
        /// </summary>
        public enum EditorContentType
        {
            /// <summary>Žádný obsah</summary>
            None,
            /// <summary>Editor</summary>
            Editor,
            /// <summary>PDF dokument</summary>
            PdfPreview
        }
        #endregion
		#region Document
		/// <summary>
		/// Iniciace dokumentu
		/// </summary>
		protected void InitDocument()
		{
            // Sestava alternativních komponent pro dílec 62271:
            // this.Document = ReportDocument.CreateFromFile("dw_testy_tab.srd");
            // this.Document.Records = new List<int>() { 62271 };

            this.Document = ReportDocument.CreateSampleDocument1();
            // this.Document = ReportDocument.CreateFromFile("dw_pruvodka_vp_s_komp_form.srd");
		}
        /// <summary>
        /// true pokud mám k dispozici dokument
        /// </summary>
        public bool HasDocument { get { return (this._Document != null); } }
		/// <summary>
		/// Data FRX dokumentu
		/// </summary>
		public ReportDocument Document
		{
			get
			{
				return this._Document;
			}
			set
			{
				this._Document = value;
				this._ReportEditor.Document = value;
                if (this.HasDocument)
                    this._Document.Form = this;
			}
		}
		private ReportDocument _Document;
		#endregion
        #region Public property
        /// <summary>
        /// Grafický editor
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public EditorControl ReportEditor { get { return this._ReportEditor; } }

        #endregion

        #region public Adapter na metody a vlastnosti privátních členů, handlery do metod dokumentu
        #region UserInterface
        /// <summary>
        /// Vrátí soupis příkazů editoru, keré vyhovují dané podmínce
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public IEnumerable<EditorCommand> UIFindCommands(Func<EditorCommand, bool> predicate)
        {
            return this._EditorUI.FindCommands(predicate);
        }
        /// <summary>
        /// Aktualizuje jednotlivé vizuální prvky (položky menu / toolbaru) podle stavů předaných v parametru této metody.
        /// </summary>
        /// <param name="itemStates"></param>
        public void UIRefresh(IEnumerable<EditorUIItemState> itemStates)
        {
            this._EditorUI.UIRefresh(itemStates);
        }
        /// <summary>
        /// Metoda, která pomáhá řešit klávesové eventy.
        /// Typický postup: Control, který má focus, dostává od Windows fyzické klávesové eventy.
        /// Aby je nemusel dekódovat sám (protože jejich klávesové zkratky mohou být konfigurovatelné !), využívá tuto metodu UI = předá ji informace o klávesách.
        /// Tato metoda zjistí, zda klávesy odpovídají některému commandu, pokud ano tak tento command provede (vytvoří Command a zavolá standardní event CommandExecute), a vrací se true = byl to příkaz.
        /// Pokud to není příkaz, pak se event nevolá a vrací se false (klávesa je nevyřešena, control si ji může řešit sám).
        /// </summary>
        /// <param name="keyModifiers">Přístupová klávesa, modifikátory (ctrl + alt + shift)</param>
        /// <param name="keyCode">Přístupová klávesa, kód bez modifikátorů</param>
        /// <param name="onlyEnabled">Příznak: vrátit command pouze tehdy, pokud jeho odpovídající Button je Enabled</param>
        /// <returns></returns>
        public bool UIKeyCodeResolve(Keys keyModifiers, Keys keyCode, bool onlyEnabled)
        {
            return this._EditorUI.KeyCodeResolve(keyModifiers, keyCode, onlyEnabled);
        }
        #endregion
        #region PropertyPanel
        /// <summary>
        /// Gets or sets the currently selected object in PropertyPanel.
        /// </summary>
        public object PropertyPanelSelectedObject
        {
            get { return this._PropertyPanel.SelectedObject; }
            set { this._PropertyPanel.SelectedObject = value; }
        }
        /// <summary>
        /// Gets or sets the currently selected objects in PropertyPanel.
        /// </summary>
        public object[] PropertyPanelSelectedObjects
        {
            get { return this._PropertyPanel.SelectedObjects; }
            set { this._PropertyPanel.SelectedObjects = value; }
        }
        /// <summary>
        /// Metoda najde v položkách Combo boxu objekt s daným ID
        /// </summary>
        /// <param name="selectID"></param>
        /// <returns></returns>
        public DComboItem PropertyComboFindItem(IComparable selectID)
        {
            return this._PropertyPanel.ComboFindDItem(selectID);
        }
        /// <summary>
        /// Aktuálně vybraný objekt v combo boxu
        /// </summary>
        public DComboItem PropertyComboSelectedItem
        {
            get { return this._PropertyPanel.ComboSelectedDItem; }
            set { this._PropertyPanel.ComboSelectedDItem = value; }
        }
        /// <summary>
        /// Seznam všech objektů v nabídce comboboxu
        /// </summary>
        public IEnumerable<DComboItem> PropertyComboItems
        {
            get { return this._PropertyPanel.ComboDItems; }
            set { this._PropertyPanel.ComboDItems = value; }
        }
        #endregion
        #region Editor
        /// <summary>
        /// Překreslí obsah editoru = zobrazený report při editaci
        /// </summary>
        public void EditorReDraw()
        {
            this.ReportEditor.ReDraw();
        }
        /// <summary>
        /// Provedení dané akce (command).
        /// Poznámka: zdejší metodu volá v zásadě jen Document, takže akce s dokumentem sem nechodí = chodí sem jen ty commandy, které nevyřešil Document v sobě.
        /// Nemusím tedy ošetřovat commandy typu DocumentSave, Load, Print, atd.
        /// </summary>
        /// <param name="runArgs"></param>
        /// <returns></returns>
        internal void EditorRunCommand(EditorCommandRunArgs runArgs)
        {
            this.ReportEditor.RunCommand(runArgs);
        }



        #endregion
        #region Privátní metody, kdy z události Formu voláme odpovídající metodu na Documentu (pokud dokument máme navázaný)
        /// <summary>
        /// Vyvolá metodu this.Document.UIRunCommand() (pokud máme dokument)
        /// </summary>
        private void CallDocumentCommandExecute(EditorCommandExecuteArgs args)
        {
            if (this.HasDocument)
                this.Document.UIRunCommand(args);
        }
        /// <summary>
        /// Vyvolá metodu this.Document.PropertyPanelEnter() (pokud máme dokument)
        /// </summary>
        protected void CallDocumentPropertyPanelEnter()
        {
            if (this.HasDocument)
                this.Document.PropertyPanelEnter();
        }
        /// <summary>
        /// Vyvolá metodu this.Document.PropertyPanelEnter() (pokud máme dokument)
        /// </summary>
        protected void CallDocumentPropertyValueChanged(PropertyValueChangedEventArgs e)
        {
            if (this.HasDocument)
                this.Document.PropertyGridValueChanged(e);
        }
        /// <summary>
        /// Vyvolá metodu this.Document.PropertyComboChanged() (pokud máme dokument)
        /// </summary>
        protected void CallDocumentPropertyComboChanged()
        {
            if (this.HasDocument)
                this.Document.PropertyComboChanged();
        }
        #endregion
        #endregion
        private void listView1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            this.DoDragDrop(e.Item, DragDropEffects.Copy);
        }

    }
}
